#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <jerror.h>





typedef struct _Image{
  unsigned char* data;
  unsigned long sizeX;
  unsigned long sizeY;
}Image;

char presse;
int anglex=30,angley=20,x,y,xold,yold;

void souris(int boutton, int etat,int x,int y);
void sourismouv(int x,int y);
void loadJPEG(const char *file, Image *image);
void display(void);
void keyboard(unsigned char key, int x, int y);

Image *image;
int main(int argc, char **argv)
{
  //init glut
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
  glutInitWindowPosition(200,200);
  glutInitWindowSize(300,300);
  glutCreateWindow("tout moche");
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);
  glutMouseFunc(souris);
  glutMotionFunc(sourismouv);
  //init GL
  
  glClearColor(0.0,0.0,0.0,0.0);
 // glShadeModel(GL_FLAT);
  glEnable(GL_DEPTH_TEST);
  


  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0,1,1.0,5.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  
  //chargement des textures
  image = (Image*) malloc(sizeof(Image));
  loadJPEG("yeux.jpg", image);
   
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->sizeX, image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);
    
    //glEnable(GL_TEXTURE_2D);

  glutMainLoop();
  return 0;
}

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();
  gluLookAt(0.0,0.0,2.5,0.0,0.0,0.0,0.0,1.0,0.0);
  glRotatef(angley,1.0,0.0,0.0);
  glRotatef(anglex,0.0,1.0,0.0);
  glEnable(GL_TEXTURE_2D);
  glBegin(GL_POLYGON);
  glTexCoord2f(0.0,0.0);   glVertex3f(-0.5, 0.5, 0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f(-0.5,-0.5, 0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f( 0.5,-0.5, 0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f( 0.5, 0.5, 0.5);
  glEnd();
  glDisable(GL_TEXTURE_2D);
  glEnable(GL_TEXTURE_2D);
  glBegin(GL_POLYGON);  
  glTexCoord2f(0.0,0.0);   glVertex3f( 0.5, 0.5, 0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f( 0.5,-0.5, 0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f( 0.5,-0.5,-0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f( 0.5, 0.5,-0.5);
  glEnd();
  glDisable(GL_TEXTURE_2D);

  glBegin(GL_POLYGON);
  glTexCoord2f(0.0,0.0);   glVertex3f( 0.5, 0.5,-0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f( 0.5,-0.5,-0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f(-0.5,-0.5,-0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f(-0.5, 0.5,-0.5);
  glEnd();

  glBegin(GL_POLYGON);
  glTexCoord2f(0.0,0.0);   glVertex3f(-0.5, 0.5,-0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f(-0.5,-0.5,-0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f(-0.5,-0.5, 0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f(-0.5, 0.5, 0.5);
  glEnd();

  glBegin(GL_POLYGON);
  glTexCoord2f(0.0,0.0);   glVertex3f(-0.5, 0.5,-0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f(-0.5, 0.5, 0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f( 0.5, 0.5, 0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f( 0.5, 0.5,-0.5);
  glEnd();
  glBegin(GL_POLYGON);
  glTexCoord2f(0.0,0.0);   glVertex3f(-0.5,-0.5,-0.5);
  glTexCoord2f(0.0,1.0);   glVertex3f(-0.5,-0.5, 0.5);
  glTexCoord2f(1.0,1.0);   glVertex3f( 0.5,-0.5, 0.5);
  glTexCoord2f(1.0,0.0);   glVertex3f( 0.5,-0.5,-0.5);
  glEnd();
  
  glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{  
  switch (key)
  {
    case 'p': /* affichage du carre plein */
      glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
      glutPostRedisplay();
      break;
    case 'f': /* affichage en mode fil de fer */
      glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
      glutPostRedisplay();
      break;
    case 's' : /* affichage en mode point */
      glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
      glutPostRedisplay();
      break;
    case 'q' : /*la touche 'q' permet de quitter le programme */
      exit(0);
    case 'c' : /*affiche CW*/
      glEnable(GL_CULL_FACE);
      glFrontFace(GL_CW);
      glutPostRedisplay();
      break;
    case 'C' : /*affiche CW*/
      glEnable(GL_CULL_FACE);
      glFrontFace(GL_CCW);
      glutPostRedisplay();
      break;
    case 'd': /* prise en compte du Z-Buffer*/
      glEnable(GL_DEPTH_TEST);
      glutPostRedisplay();
      break;
    case 'D': /* pas de prise en compte du Z-Buffer*/
      glDisable(GL_DEPTH_TEST);
      glutPostRedisplay();
      break;
    case 'l': /* prise en compte du modele d'eclairage*/
      glEnable(GL_LIGHTING);
      glutPostRedisplay();
      break;
    case 'L': /* pas de prise du modele d'eclairage*/
      glDisable(GL_LIGHTING);
      glutPostRedisplay();
      break;
    default :
      break;
  }
}

void loadJPEG(const char *fichier, Image *image)
{
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  int taille_ligne;
  FILE *file;	
  unsigned char *ligne;
  int size;
  
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);
  if ((file=fopen(fichier,"rb"))==NULL)
    {
      fprintf(stderr,"Erreur : impossible d'ouvrir le fichier texture.jpg\n");
      exit(1);
    }
  jpeg_stdio_src(&cinfo, file);
  jpeg_read_header(&cinfo, TRUE);

  /*if ((cinfo.image_width!=256)||(cinfo.image_height!=256)) {
    fprintf(stdout,"Erreur : l'image doit etre de taille 256x256\n");
    exit(1);
  }*/
  image->sizeX = cinfo.image_width;
  image->sizeY = cinfo.image_height;
  size = cinfo.image_width * cinfo.image_height * 3;
  image->data = (unsigned char*)malloc(size*sizeof(unsigned char));
  if (cinfo.jpeg_color_space==JCS_GRAYSCALE) {
    fprintf(stdout,"Erreur : l'image doit etre de type RGB\n");
    exit(1);
  }

  jpeg_start_decompress(&cinfo);
  ligne=image->data;
  taille_ligne = cinfo.image_width;
  while (cinfo.output_scanline<cinfo.output_height)
    {
      ligne=image->data+3*taille_ligne*cinfo.output_scanline;
      jpeg_read_scanlines(&cinfo,&ligne,1);
    }
  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  //TODO il faut inverser le rouge et le bleu
}

void souris(int bouton, int etat,int x,int y)
{
  if (bouton == GLUT_LEFT_BUTTON && etat == GLUT_DOWN) 
  {
    presse = 1;
    xold = x; 
    yold=y;
  }
  if (bouton == GLUT_LEFT_BUTTON && etat == GLUT_UP) 
    presse=0; 
}

void sourismouv(int x,int y)
{
    if (presse)
    {
      anglex=anglex+(x-xold); 
      angley=angley+(y-yold);
      glutPostRedisplay();
    }
    
    xold=x; 
    yold=y;
}
